package DAO.impl;

import java.io.Serializable;
import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;

import DAO.GenericDAO;
import DAO.HibernateUtil;

/**
 * 
 * Base implementation of GenericDAO interface, contains CRUD operations
 * and some queries to get all, or some specific type of entity
 *  
 * @param <T> - an entity class 
 * @param <ID> - id class which is used to describes id's of entities.
 */
public class GenericDAOImpl<T, ID> implements GenericDAO<T, ID> {

	/**
	 * Get current open session using {@link HibernateUtil} 
	 * @return an opened session for this thread
	 */
	protected Session getSession() {
		return HibernateUtil.getSession();
	}
	
	/**
	 * Saves or updates given entity to the DB
	 */
	public void save(T entity) {
		Session hibernateSession = this.getSession();
		hibernateSession.saveOrUpdate(entity);

	}

	/**
	 * Merges given entity to the DB
	 */
	public void merge(T entity) {
		Session hibernateSession = this.getSession();
		hibernateSession.merge(entity);

	}

	/**
	 * Delete given entity from the DB
	 */
	public void delete(Object entity) {
		Session hibernateSession = this.getSession();
		hibernateSession.delete(entity);

	}

	/**
	 * Find all entities of the given type class type in the DB
	 */
	@SuppressWarnings("unchecked")
	public List<T> findAll(Class<? extends Serializable> clazz) {
		List<T> t = null;
		Session hibernateSession = this.getSession();
		Query query = hibernateSession.createQuery("from " + clazz.getName());
		t = (List<T>) query.list();
		return t;
	}

	/**
	 * Find many entities according to the query in the DB
	 */
	@SuppressWarnings("unchecked")
	public List<T> findMany(Query query) {
		List<T> t = null;
		t = (List<T>) query.list();
		return t;
	}

	/**
	 * Find one entity according to the query in the DB
	 */
	@SuppressWarnings("unchecked")
	public T findOne(Query query) {
		T t = null;
		t = (T) query.uniqueResult();
		return t;
	}

	/**
	 * Find one entity according to the given ID and class type in the DB
	 */
	@SuppressWarnings("unchecked")
	public T findByID(Class<? extends Serializable> clazz, Integer id) {
		T t = null;
		Session hibernateSession = this.getSession();
		t = (T) hibernateSession.get(clazz, id);

		return t;
	}

}
